In [7]:
def function(x):
return x+1, x+2
assert function(10) == (11,12)
# example usage
answer = function(10)
print 'function(100) -> {}'.format(answer)
In [9]:
def generator(x):
yield x+1
yield x+2
assert list(generator(10)) == [11, 12]
# example usage
for x in generator(10):
print 'generator(10) -> {}'.format(x)
In [12]:
generator_expression = (x+1 for x in [1,2,4,8,16])
assert list(generator_expression) == [2,3,5,9,17]
In [11]:
generator_expression = (x+1 for x in [1,2,4,8,16])
# example usage
for x in generator_expression:
print 'generator_expression -> {}'.format(x)
In [13]:
generator_expression = lambda: (x+1 for x in [1,2,4,8,16])
assert list(generator_expression()) == [2,3,5,9,17]
# example usage
for x in generator_expression():
print 'generator_expression() -> {}'.format(x)
In [17]:
class Callable(object):
def __call__(self, x):
return x + 1, x + 2
assert Callable()(10) == (11, 12)
# exampe usage
answer = Callable()(10)
print 'Callable(10) -> {}'.format(answer)
In [20]:
class Callable(object):
@staticmethod
def __call__(x):
return x + 1, x + 2
assert Callable()(10) == (11, 12)
In [22]:
from collections import Callable
def function():
pass
assert callable(function) # deprecated in Python 3
assert isinstance(function, Callable)
In [21]:
some_list = [1, 1, 2, 3, 5]
for x in some_list:
print 'some_list -> {}'.format(x)
In [29]:
class Iterable(object):
def __init__(self, x):
self.x = x
self.state = 0
def __iter__(self):
return self # this object is both an iterator and an iterable
def __next__(self):
if self.state == 2:
raise StopIteration
rv = self.x + self.state
self.state += 1
return rv
next = __next__ # Python 3 calls it `__next__`; Python 2 calls it `next`
assert list(Iterable(10)) == [10, 11]
# example usage
for x in Iterable(10):
print 'Iterable(10) -> {}'.format(x)
In [33]:
from collections import Iterator, Iterable
some_list = [1, 1, 2, 3, 5]
assert isinstance(some_list, Iterable) and not isinstance(some_list, Iterator)
some_iter = iter(some_list)
assert isinstance(some_iter, Iterable) and isinstance(some_iter, Iterator)
In [34]:
def generator(x):
yield x+1
yield x+2
assert list(generator(10)) == [11, 12]
In [41]:
def generator(x):
yield x+1
yield x+2
assert list(generator(10)) == [11, 12]
# support for next(), .next()
g = generator(10)
print 'next(g) -> {}'.format(next(g)) # these two lines are
print 'next(g) -> {}'.format(g.next())
# next too many times, and we get a StopIteration
try:
next(g)
except StopIteration as e:
print 'next(g) -> {!r}'.format(e)
In [53]:
from sys import exc_info
from traceback import print_tb
def generator(x):
yield x+1
yield x+2
g = generator(10)
print 'next(g) -> {}'.format(next(g))
# print 'next(g) -> {}'.format(next(g))
# support for .throw
try:
g.throw(ValueError('raised value error'))
except ValueError as e:
print 'g.throw(ValueError) -> {!r}'.format(e)
_, _, traceback = exc_info()
print_tb(traceback)
In [57]:
def generator(x):
yield x+1
yield x+2
g = generator(10)
print 'next(g) -> {}'.format(next(g))
g.close()
try:
next(g)
except StopIteration as e:
print 'g.close()'
print 'next(g) -> {!r}'.format(e)
In [59]:
def generator(x):
y = None
y = yield x+1, y
y = yield x+2, y
g = generator(10)
print 'next(g) -> {}'.format( g.next() )
print 'g.send("abc") -> {}'.format( g.send("abc") )
In [61]:
def generator(x):
yield x + 1
g = generator(10)
g.send(10)
In [3]:
# an example of a generalisation: slicing
from itertools import islice
# standard lists can be sliced
some_list = [1, 1, 2, 3, 5, 8]
print some_list[1:5]
# abstract iterables can be isliced
def fibonacci(a=1, b=1):
while True:
yield a
a, b = b, a+b
print list(islice(fibonacci(),1,5))
# other examples: izip, imap, ifilter (Python2)
In [4]:
# an example of a helper: chain
from itertools import chain, islice
# standard lists can be appended
some_list = [1, 1, 2, 3, 5, 8]
some_list = [0] + some_list
print some_list
# abstract iterables can be chained
def fibonacci(a=1, b=1):
while True:
yield a
a, b = b, a+b
f = fibonacci()
f = chain([0], f)
print list(islice(f,0,7))
# other examples: tee, repeat, cycle
In [7]:
# an example of an algorithm: takewhile
from itertools import takewhile
# take elements as long as some predicate is True
def fibonacci(a=1, b=1):
while True:
yield a
a, b = b, a+b
print list(takewhile(lambda n: n < 50, fibonacci()))
# other examples: dropwhile, product, combinations, permutations
In [16]:
def pairwise(xs):
xs = iter(xs)
pairings = []
x = next(xs)
for y in xs:
pairings.append([x,y])
x = y
return pairings
print pairwise(xrange(10))
# print pairwise(xrange(1000000))
In [1]:
def pairwise(xs):
xs = iter(xs)
x = next(xs)
for y in xs:
yield x, y
x = y
print list(pairwise(xrange(10)))
print pairwise(xrange(1000000))
In [20]:
from itertools import tee, izip, islice
nwise = lambda g,n=2: izip(*(islice(g,i,None) for i,g in enumerate(tee(g,n))))
print list(nwise(xrange(10)))
In [2]:
from math import ceil, sqrt
isprime = lambda n: 1 < n < 4 or all(n % d for d in xrange(2,int(ceil(sqrt(n)))+1,2))
%timeit -n100 isprime(11984395091324)
In [3]:
from math import ceil, sqrt
def isprime(n):
if 1 < n < 4:
return True
for d in xrange(2, int(ceil(sqrt(n)))+1, 2):
if n % d == 0:
return False
return True
%timeit -n100 isprime(11984395091324)
In [4]:
from math import ceil, sqrt
isprime = lambda n, ng: 1 < n < 4 or all(ng)
n = 11984395091324
ng = (n % d for d in xrange(2,int(ceil(sqrt(n)))+1,2))
%timeit -n100 isprime(n, ng)
In [56]:
def fibonacci(n, a=1, b=1):
rv = [a, b]
while rv[-1] + rv[-2] < n:
rv.append(rv[-1] + rv[-2])
return rv
print fibonacci(20)
print set(fibonacci(20))
print tuple(fibonacci(20))
% timeit fibonacci(20000)
% timeit set(fibonacci(20000))
% timeit tuple(fibonacci(20000))
In [58]:
def fibonacci(n, a=1, b=1):
while a < n:
yield a
a, b = b, a+b
print list(fibonacci(20))
print set(fibonacci(20))
print tuple(fibonacci(20))
%timeit set(fibonacci(20000))
%timeit list(fibonacci(20000))
%timeit tuple(fibonacci(20000))
In [62]:
# fibonacci numbers up to but not exceeding n
def fibonacci(n, a=1, b=1):
rv = [a, b]
while rv[-1] + rv[-2] < n:
rv.append(rv[-1] + rv[-2])
return rv
print fibonacci(20)
In [63]:
# fibonacci numbers up to but not exceeding n
def fibonacci(n, a=1, b=1):
rv = [a, b]
for _ in xrange(2,n):
rv.append(rv[-1] + rv[-2])
return rv
print fibonacci(20)
In [65]:
from itertools import takewhile, islice
def fibonacci(a=1, b=1):
while True:
yield a
a, b = b, a+b
print list(islice(fibonacci(), 0, 20)) # first twenty values
print list(takewhile(lambda n: n < 20, fibonacci())) # values up to but not exceeding 20
In [67]:
from time import sleep
# fibonacci numbers up to but not exceeding n
def fibonacci(n, a=1, b=1):
rv = [a, b]
for _ in xrange(2,n):
rv.append(rv[-1] + rv[-2])
sleep(.01)
return rv
print fibonacci(20)[0]
% timeit fibonacci(20)[0]
In [68]:
from time import sleep
def fibonacci(a=1, b=1):
while True:
yield a
a, b = b, a+b
sleep(.01)
print next(fibonacci())
% timeit next(fibonacci())
In [103]:
from datetime import date, timedelta
from time import sleep
holidays = { 'new years': date(2013, 1, 1),
'mlk day': date(2013, 1, 21),
'presidents day': date(2013, 2, 18),
'good friday': date(2013, 3, 29),
'memorial': date(2013, 5, 27),
'independence day': date(2013, 6, 4),
'labour day': date(2013, 9, 2),
'columbus day': date(2013, 10, 14),
'veterans day': date(2013, 11, 11),
'thanksgiving': date(2013, 11, 29),
'christmas': date(2013, 12, 24) }
def next_business_day(refdate, n=1, holidays=set(holidays.values())):
sleep(.01)
while refdate.weekday() in (5,6) or refdate in holidays:
refdate += timedelta(days=1)
while n:
refdate += timedelta(days=1)
while refdate.weekday() in (5,6) or refdate in holidays:
refdate += timedelta(days=1)
n -= 1
return refdate
# July August September
# Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
# 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 7
# 7 8 9 10 11 12 13 4 5 6 7 8 9 10 8 9 10 11 12 13 14
# 14 15 16 17 18 19 20 11 12 13 14 15 16 17 15 16 17 18 19 20 21
# 21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28
# 28 29 30 31 25 26 27 28 29 30 31 29 30
print next_business_day(date(2013, 8, 30))
print next_business_day(date(2013, 9, 1))
def next_business_days(refdate, n=10):
next_days = [next_business_day(refdate)]
for _ in xrange(n-1):
next_days.append(next_business_day(ten_days[-1]))
return next_days
print next_business_days(date(2013, 1, 1), 10)
% timeit next_business_days(date(2013, 1, 1), 90)
In [104]:
def next_business_days(refdate, holidays=set(holidays.values())):
sleep(.01)
while refdate.weekday() in (5,6) or refdate in holidays:
refdate += timedelta(days=1)
while True:
refdate += timedelta(days=1)
while refdate.weekday() in (5,6) or refdate in holidays:
refdate += timedelta(days=1)
yield refdate
print list(islice(next_business_days(date(2013, 1, 1)), None, 10))
% timeit list(islice(next_business_days(date(2013, 1, 1)), None, 90))
In [3]:
from functools import wraps
# messy
def pumped(gen):
@wraps(gen)
def inner(*args, **kwargs):
g = gen(*args, **kwargs)
next(g)
return g.send
return inner
In [4]:
@pumped
def predicate(x, state=0):
value = yield
while True:
if state+value <= x: # take values until you exceed the maximum
state += value
value = yield True
else:
value = yield False
from itertools import repeat, chain, takewhile
greedy = lambda items, predicate: chain.from_iterable(takewhile(predicate,repeat(x)) for x in items)
In [14]:
from __future__ import division, unicode_literals
from itertools import groupby
from random import randint
denominations = [1,5,10,25,100,500,1000,2000]
for _ in xrange(10):
amount = randint(0,1000) # randomly pick a dollar amount
pred = predicate(amount) # create the predicate
coins = greedy(reversed(denominations), pred) # greedy algorithm
# pretty print
print 'your change for {:>5.2f}$ = {}'.format(amount/100,
' + '.join('{:>2d}×{:<3}'.format(sum(1 for _ in cs),
(('{:d}¢' if c < 100 else '{:.0f}$').format(c if c < 100 else c/100))) for c,cs in groupby(coins)))
In [23]:
roman = { 1: 'i', 4: 'iv', 5: 'v', 9: 'ix', 10: 'x',
40: 'ix', 50: 'x', 90: 'xc', 100: 'c', 400: 'cd',
500: 'd', 900: 'cm', 1000: 'm',}
for _ in xrange(10):
year = randint(1900,2200) # randomly pick a year
pred = predicate(year) # create the predicate
numerals = greedy(reversed(sorted(roman)), pred) # greedy algorithm
# pretty print
print 'the year {} is written {}'.format( year,''.join(roman[x].upper() for x in list(numerals)))
In [ ]:
from itertools import repeat, izip, count, chain
from random import randrange
from time import sleep
# helper function
sleep = lambda n, sleep=sleep: lambda: sleep(n)
randoms = (randrange(0,63) for _ in count())
pauses = chain(repeat(sleep(0), 2500), repeat(sleep(0.01), 250), repeat(sleep(0.1), 25), repeat(sleep(1), 5))
for pause, random in izip(pauses, randoms):
pause()
print random
In [153]:
# ref: en.wikipedia.org/wiki/Mersenne_twister
def mersenne(seed = 1, period=397, length=624):
state, tm = [seed & 0xffffffff], lambda op, x: x ^ op(x)
for i in xrange(1,length):
state.append((0x6c078965 * (state[-1] ^ (state[-1] >> 30)) + i) & 0xffffffff)
while True:
for i in xrange(length):
y = (state[i] & 0x80000000) + (state[(i+1)%length] & 0x7fffffff)
state[i] = (state[(i+period)%length] ^ (y >> 1)) ^ (0x9908b0df if y%2 else 0)
for i in xrange(length):
yield tm(lambda x: x >> 18, tm(lambda x: (x << 15) & 0xefc60000, tm(lambda x: (x << 7) & 0x9d2c5680, tm(lambda x: x >> 11, state[i]))))
from itertools import takewhile
def randrange(start, stop, mersenne=mersenne(seed=1)):
size = 2**32 // (stop - start)
return start + next(takewhile(lambda x: 0 <= x < (stop-start)*size,mersenne)) % (stop-start)
m = mersenne()
assert list(islice(m,0,10)) == [1791095845, 4282876139, 3093770124, 4005303368, 491263, 550290313, 1298508491, 4290846341, 630311759, 1013994432]
In [ ]:
from random import randrange
class Wheel(object):
def __init__(self, start=0, players=100):
self.start = start
self.players = players
def spin(self):
state = self.start
for _ in xrange(randrange(100,200)):
print '| {:>2f} |'.format(self.state)
self.state = (self.state + 1) % players
# ...
In [38]:
from __future__ import division
from time import sleep
from random import random
forward, backward = lambda n: n+1, lambda n: n-1
def wheel(iterable, state=0, direction=forward):
values = list(iterable)
while True:
direction = (yield values[state]) or direction
state = direction(state) % len(values)
transition = lambda v,t: v-v/abs(v)*5*random()-abs(v)/(2+random())*t
def spin(wheel, velocity=500, stop=0.25, transition=transition):
next(wheel) # ugly
while abs(velocity) > stop:
yield wheel.send(forward if velocity > 0 else backward)
sleep(1/abs(velocity))
velocity = transition(velocity,1/velocity)
In [26]:
def spin(wheel, velocity=500, stop=0.25, transition=transition):
next(wheel) # ugly
while abs(velocity) > stop:
yield wheel.send(lambda n: n + int(velocity)) # <--
sleep(1/abs(velocity))
velocity = transition(velocity,1/velocity)
In [45]:
w = wheel([0,1,2])
assert next(w) == 0
assert next(w) == 1
assert next(w) == 2
assert next(w) == 0
assert next(w) == 1
w = wheel([0,1,2], direction=backward)
assert next(w) == 0
assert next(w) == 2
assert next(w) == 1
assert next(w) == 0
assert next(w) == 2
w = wheel([0,1,2], direction=lambda n: n+3)
assert next(w) == 0
assert next(w) == 0
w, v = wheel([0,1,2]), wheel(xrange(3))
assert next(w) == next(v)
assert next(w) == next(v)
w = wheel([0,1,2])
% timeit list(spin(w, velocity=10, stop=10))
% timeit list(spin(w, velocity=10, stop=0, transition=lambda v,t: v-5*v*t))
In [161]:
friction = lambda v,t: v-v/abs(v)*5*random()-abs(v)/(2+random())*t
def velocity(start=500, stop=0.25, friction=friction):
state = start
while abs(state) > stop:
yield state
state = friction(state, 1/state)
def spin(wheel, velocity):
next(wheel) # ugly
for vel in velocity:
yield wheel.send(lambda n: n + int(vel))
sleep(1/abs(vel))
In [170]:
v = velocity(500, 0.25)
assert next(v) > next(v)
v = velocity(500, 0.25)
assert list(v)
v = velocity(500, 0.25)
print list(v)
In [173]:
from __future__ import division
from time import sleep
from random import random
forward, backward = lambda n: n+1, lambda n: n-1
def wheel(iterable, state=0, direction=forward):
values = list(iterable)
while True:
direction = (yield values[state]) or direction
state = direction(state) % len(values)
friction = lambda v,t: v-v/abs(v)*5*random()-abs(v)/(2+random())*t
def velocity(start=500, stop=0.25, friction=friction):
state = start
while abs(state) > stop:
yield state
state = friction(state, 1/state)
def spin(wheel, velocity):
next(wheel) # ugly
for vel in velocity:
yield wheel.send(lambda n: n + int(vel))
sleep(1/abs(vel))
In [174]:
from random import randrange, shuffle
players, prizes = range(25), ['book'] + ['t-shirt']*5 + ['mug']*5
winners = [(player, prize) for player in players for prize in prizes]
shuffle(winners)
state, velocity = randrange(0, len(winners)), velocity(randrange(500, 750))
for number, prize in spin(wheel(winners, state=state), velocity=velocity):
print '| {:>2} {:<{}} |'.format(number, prize, max(len(p) for p in prizes))
print 'you won a ... {}, #{}'.format(prize, number)